home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_10_03
/
1003054b
< prev
next >
Wrap
Text File
|
1991-10-05
|
7KB
|
269 lines
/* ----------------------------------------------------
* LISTING 5
*
* Filename: tape.c
* Summary: State machine constructs for
* tape device
* Author: T.W. Nelson
* Compile options:
* Version: 1.00
* Date: 07-Oct-1991
* Notes:
*
* Source code Copyright (c) 1991 T.W. Nelson.
* May be used only with appropriate
* acknowledgement of copyright.
* ------------------------------------------------- */
#include "driver.h"
#include "tape.h"
extern void putstr( const char *str );
extern int initialize(), status(), eject(), record(),
play(), fforward(), rewind(), stop(), cstate(),
shutdown();
//Arrays of function pointers to be executed
//in the order listed, to effect transition from
//the current state to next desired state.....
//
int (*f_init[])() = { initialize, cstate, 0 };
int (*f_stat[])() = { status, cstate, 0 };
int (*f_off[])() = { shutdown, cstate, 0 };
int (*f_ejoff[])() = { eject, shutdown, cstate, 0 };
int (*f_eject[])() = { eject, cstate, 0 };
int (*f_rec[])() = { record, cstate, 0 };
int (*f_play[])() = { play, cstate, 0 };
int (*f_ffwd[])() = { fforward, cstate, 0 };
int (*f_rwnd[])() = { rewind, cstate, 0 };
int (*f_stop[])() = { stop, cstate, 0 };
int (*f_steject[])() = { stop, eject, cstate, 0 };
int (*f_strec[])() = { stop, record, cstate, 0 };
int (*f_stplay[])() = { stop, play, cstate, 0 };
int (*f_stffwd[])() = { stop, fforward, cstate, 0 };
int (*f_strwnd[])() = { stop, rewind, cstate, 0 };
//Event (Command) Tables describing valid events for a
//state, the next state to transition to, as well as
//the functions to effect the transition......
//
S_TAB s_off[] = {
/* command n_state funcs
--------------------------------- */
CMD_POWER_ON, ON, f_init,
CMD_CHK_STATUS, OFF, f_stat,
END, END, 0, };
S_TAB s_on[] = {
/* command n_state funcs
------------------------------------ */
CMD_POWER_OFF, OFF , f_off,
CMD_INSERT , READY, f_stat,
CMD_CHK_STATUS, ON, f_stat,
END , END , 0, };
S_TAB s_ready[] = {
/* command n_state funcs
------------------------------------ */
CMD_POWER_OFF , OFF , f_ejoff,
CMD_EJECT , ON , f_eject,
CMD_RECORD , RECORD , f_rec,
CMD_PLAY , PLAY , f_play,
CMD_FFORWARD , FFORWARD, f_ffwd,
CMD_REWIND , REWIND , f_rwnd,
CMD_CHK_STATUS, READY , f_stat,
END , END , 0, };
S_TAB s_record[] = {
/* command n_state funcs
------------------------------------ */
CMD_STOP , READY , f_stop,
CMD_EJECT , ON , f_steject,
CMD_FFORWARD , FFORWARD, f_stffwd,
CMD_PLAY , PLAY , f_stplay,
CMD_REWIND , REWIND , f_strwnd,
CMD_CHK_STATUS, RECORD , f_stat,
END , END , 0, };
S_TAB s_play[] = {
/* command n_state funcs
------------------------------------ */
CMD_STOP , READY , f_stop,
CMD_EJECT , ON , f_steject,
CMD_FFORWARD , FFORWARD, f_stffwd,
CMD_REWIND , REWIND , f_strwnd,
CMD_RECORD , RECORD , f_strec,
CMD_CHK_STATUS, PLAY , f_stat,
END , END , 0, };
S_TAB s_fforward[] = {
/* command n_state funcs
------------------------------------ */
CMD_STOP , READY , f_stop,
CMD_EJECT , ON , f_steject,
CMD_PLAY , PLAY , f_stplay,
CMD_REWIND , REWIND , f_strwnd,
CMD_RECORD , RECORD , f_strec,
CMD_CHK_STATUS, FFORWARD, f_stat,
END , END , 0, };
S_TAB s_rewind[] = {
/* command n_state funcs
------------------------------------ */
CMD_STOP , READY , f_stop,
CMD_EJECT , ON , f_steject,
CMD_PLAY , PLAY , f_stplay,
CMD_RECORD , RECORD , f_strec,
CMD_FFORWARD , FFORWARD, f_stffwd,
CMD_CHK_STATUS, REWIND , f_stat,
END , END , 0, };
//The actual "state table" that connects all
//the foregoing initialized data into one. enum
//'device_states' is an index into this array
//of struct pointers. These MUST be in same order
//as the enum in 'tape.h' ........
//
S_TAB *s_table[] = {
s_off, s_on, s_ready, s_record, s_play,
s_fforward, s_rewind,
};
unsigned tape_io( CMDARG far *arg )
{
/* State Machine Driver. Called by DOS thru driver
* interrupt routine, command codes 3 & 12.
*/
int i;
S_TAB *pcmd; //-> event (cmd) table
int (**pfun)(CMDARG far *arg); //-> function list
//point to the correct event table .....
if( arg->c_state >= MAX_STATE )
return IS_ERROR + INV_COMMAND;
pcmd = s_table[arg->c_state];
//find the specified command in the event table...
for( i = 0; pcmd[i].event != END; i++ )
if( pcmd[i].event == arg->cmd )
break;
//check for invalid command .....
if( pcmd[i].event == END ) {
putstr("Invalid command specified\r\n");
return IS_ERROR + INV_COMMAND;
}
//indicate next state for application .......
arg->c_state = pcmd[i].n_state;
//execute the function list ........
pfun = pcmd[i].procs;
for( i = 0; pfun[i]; i++ )
(*pfun[i])(arg);
return 0;
}
int status(CMDARG far *arg)
{
arg->status = OK;
return 0;
}
int initialize(CMDARG far *arg)
{
putstr("Device initialized\r\n" );
status(arg);
return 0;
}
int eject(CMDARG far *arg)
{
putstr( "Cassette ejected\r\n" );
status(arg);
return 0;
}
int record(CMDARG far *arg)
{
putstr( "Recording\r\n" );
status(arg);
return 0;
}
int play(CMDARG far *arg)
{
putstr( "Playing\r\n" );
status(arg);
return 0;
}
int fforward(CMDARG far *arg)
{
putstr( "Fast forwarding\r\n" );
status(arg);
return 0;
}
int rewind(CMDARG far *arg)
{
putstr( "Rewinding\r\n" );
status(arg);
return 0;
}
int stop(CMDARG far *arg)
{
putstr( "Stopping\r\n" );
status(arg);
return 0;
}
int shutdown(CMDARG far *arg)
{
putstr( "Powered down\r\n" );
status(arg);
return 0;
}
int cstate(CMDARG far *arg)
{
/* Print current state, after transition .... */
static char *s_name[] = {
"OFF", //0
"ON", //1
"READY", //2
"RECORD", //3
"PLAY", //4
"FFORWARD", //5
"REWIND", //6
};
putstr( "Current state is " );
putstr( s_name[arg->c_state] );
putstr( "\r\n" );
return 0;
}
/* ----- End of File ------------------------------- */